﻿/*
 * Author: M.Aldworth of InfiniteDesigns.org
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Security.Permissions;

namespace SVNCleaner
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //If no arguments exist, don't continue
                if (args.Length != 2)
                {
                    Console.WriteLine("Please have only 2 arguments, the operation to be performed and the directory path.");
                    return;
                }

                //If the directory doesn't exist, don't continue
                if (!Directory.Exists(args[1]))
                {
                    Console.WriteLine("The argument provided wasn't a valid directory");
                    return;
                }

                switch (args[0])
                {
                    case "-removeallsvn":
                        RemoveAllSvn(args[1]);
                        break;
                    case "-removeallbutrootsvn":
                        RemoveAllFilesButRootSvn(args[1]);
                        break;
                    case "-removerepofiles":
                        RemoveAllRepoFiles(args[1]);
                        break;
                    default:
                        Console.WriteLine("Invalid action parameter, please use one of the following...\n-removeallsvn\n-removeallbutrootsvn\n-removerepofiles");
                        break;
                }

                Console.WriteLine("Successfully removed all .svn folders from directory");
            }
            //Output all exceptions to a text file, for debugging if necessary.
            catch (Exception e)
            {
                string fileName = args[1].Substring(args[1].LastIndexOf('\\')) + ".txt";

                string logsPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\\SVN Cleaner\\Logs";

                if (!Directory.Exists(logsPath))
                    Directory.CreateDirectory(logsPath);

                StreamWriter sw = new StreamWriter(logsPath + "\\" + fileName, true);

                sw.WriteLine(Environment.NewLine + DateTime.Now.ToString());
                sw.WriteLine("Message: "+e.Message);
                sw.WriteLine("Source: "+e.Source);
                sw.WriteLine("StackTrace: " + e.StackTrace);
                sw.Close();
            }
        }

        private static void RemoveAllSvn(string directory)
        {
            //Recursively gets all files within the given directory, to be used to change any files that may be ReadOnly, to Normal
            string[] fileResults = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);

            //For some wierd reason all-wcprops couldn't would throw UnauthorizedAccessException when the Directory.Delete was being executed.
            //After changing all ReadOnly files to Normal, it worked like a charm.
            foreach (string file in fileResults)
            {
                //Normally this would change every file within the project to be Normal. We don't want this as some users may have non .svn files that are ReadOnly
                //We execute this if clause.
                if (file.Contains("\\.svn"))
                    File.SetAttributes(file, FileAttributes.Normal);
            }

            //Finally recursively gets all directories marked as .svn
            string[] dirResults = Directory.GetDirectories(directory, "*.svn", SearchOption.AllDirectories);

            foreach (string dir in dirResults)
            {
                //Somewhat redundant, but better safe than sorry
                if (Directory.Exists(dir))
                    Directory.Delete(dir, true);
            }
        }

        private static void RemoveAllFilesButRootSvn(string directory)
        {
			//Check if any .svn directory exists in top directory, if not, then don't even try to remove files because they might have accidentally clicked it
            if (Directory.GetDirectories(directory, "*.svn", SearchOption.TopDirectoryOnly).Length != 1)
                return;
		
            //Recursively gets all files within the given directory, to be used to change any files that may be ReadOnly, to Normal
            string[] fileResults = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);

            //For some wierd reason all-wcprops couldn't would throw UnauthorizedAccessException when the Directory.Delete was being executed.
            //After changing all ReadOnly files to Normal, it worked like a charm.
            foreach (string file in fileResults)
            {
                //This if statement makes sure we don't delete the root directories .svn files
                if (!file.Contains(directory + "\\.svn"))
                {
                    File.SetAttributes(file, FileAttributes.Normal);
                    File.Delete(file);
                }
            }

            //Finally recursively gets all directories marked as .svn
            string[] dirResults = Directory.GetDirectories(directory, "*", SearchOption.AllDirectories);

            foreach (string dir in dirResults)
            {
                //The first check is somewhat redundant, but better safe than sorry.
                //This if statement, removes any lingering directories, and also makes sure we don't delete the root .svn directory.
                if (Directory.Exists(dir) && !dir.Contains(directory+"\\.svn"))
                    Directory.Delete(dir, true);
            }
        }

        private static void RemoveAllRepoFiles(string directory)
        {
            //Finally recursively gets all directories marked as .svn
            string[] dirResults = Directory.GetDirectories(directory, "*.svn", SearchOption.AllDirectories);
            
            //Loop through each .svn directory looking for the \\text-base files
            //Each file in here is a repository file, therefore when we have a list of these files
            //we know what files can be deleted from the directory.
            foreach (string dir in dirResults)
            {
                string[] files = Directory.GetFiles(dir + "\\text-base");

                //Loops through each repo file and deletes it.
                foreach (string file in files)
                {
                    string fileToDelete = file.Substring(file.LastIndexOf("\\"), file.IndexOf(".svn-base") - file.LastIndexOf("\\"));

                    File.Delete(dir.Substring(0, dir.IndexOf("\\.svn")) + "\\" + fileToDelete);
                }
            }
        }

    }
}
